package com.hmdp.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.hmdp.dto.UserDTO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/*
    无论前端访问的路径是否需要校验登录，都应该刷新缓存中用户信息的有效期
    该拦截器先于LoginInterceptor执行，目的是根据token查询用户信息，(若存在)将
    用户信息保存到ThreadLocal，并刷新用户信息的有效期
 */
public class TokenRefreshInterceptor implements HandlerInterceptor {

    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 使用构造器的方法完成依赖注入(LoginInterceptor类中不能直接依赖注入)
     * @param redisTemplate
     */
    public TokenRefreshInterceptor(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        //1. 根据cookie中的sessionId获取session
//        HttpSession session = request.getSession();
//        //2. 从session中获取用户信息
//        UserDTO userDTO = (UserDTO) session.getAttribute("user");
        //TODO 压测调试，，将用户信息存入ThreadLocal后直接放行
        //1. 获取请求头中的token
        String token = request.getHeader(SystemConstants.TOKEN_HEADER);
        if (StrUtil.isBlank(token)) {
            return true;
        }
        //2. 从redis中获取用户信息
        Map<Object, Object> userMap = redisTemplate.opsForHash().entries(RedisConstants.LOGIN_USER_KEY + token);
        //3. 判断用户是否存在，不存在则放行交给下一级拦截
        if (userMap.isEmpty()) {
            return true;
        }
        //4. 将用户信息保存到ThreadLocal，以便后LoginInterceptor续拦截器和Controller拿到
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        UserHolder.saveUser(userDTO);
//        //TODO 永不过期，方便调试
//        //5. 刷新redis中token的有效期
//        redisTemplate.expire(RedisConstants.LOGIN_USER_KEY + token, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);//有效期30min
//        //6. 放行
        return true;
    }
}
